#ifndef LIBRPMCPP_H
#define LIBRPMCPP_H

extern "C" {
#include <rpm/rpmts.h>
#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <rpm/rpmfi.h>
#include <rpm/rpmgi.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmmacro.h>
#include <inttypes.h>
}

#include <list>
#include <string>

namespace librpm {

/**
 * @brief The EFieldType enum fields项的类型
 * @attention 当前的 EN_PGPSIG 不被处理
 */
enum EFieldType
{
    EN_STR,
    EN_DATE,
    EN_LONG,
    EN_PGPSIG,
};

/**
 * @brief The FieldType struct 每个项的说明信息
 */
struct FieldType
{
    std::string name;
    int type;
};

/**
 * @brief The FieldContent struct 每个项的内容，当前只能调用静态方法创建对象，只能在堆上分配
 */
class FieldContent
{
public:
    union
    {
        struct
        {
            char *ptr;
            size_t len;
        } str;
        int64_t num;
    } content;
    int type;       // FieldType，其中date是一个时间格式的str
    std::string name;

    /**
     * @brief new_string_field 创建字节流存储结构，如果是字符串类型，需要在传入是，调用者将长度+1
     * @param name field项名称
     * @param str 自己流指针
     * @param len 字节流长度
     * @return FieldContent结构
     */
    static FieldContent *new_string_field(const char *name, const char *str, size_t len);

    /**
     * @brief new_number_field 创建数值类型的存储结构
     * @param name field名称
     * @param number 数值
     * @return field对象
     */
    static FieldContent *new_number_field(const char *name, int64_t number);

    /**
     * @brief del_field 释放数据结构，当前对象只能通过new_xxxx 和del_field释放
     * @param self 对象指针
     */
    static void del_field(FieldContent *self);

private:
    FieldContent();
    FieldContent(const FieldContent &);
    ~FieldContent();
    FieldContent & operator = (const FieldContent & other);
};

typedef std::list<FieldContent*> TFieldContents;

struct SoftwarePackageInfos
{
    std::string m_software_name;
    TFieldContents m_fields;
};

typedef std::list<SoftwarePackageInfos> TSoftwareList;

/**
 * @brief 默认的查询项信息
 */
const FieldType g_default_fields[] {
    {"NAME",        EN_STR},
    {"VERSION",     EN_STR},
    {"VENDOR",      EN_STR},
    {"RELEASE",     EN_STR},
    {"BUILDTIME",   EN_DATE},
    {"INSTALLTIME", EN_DATE},
    {"BUILDHOST",   EN_STR},
    {"GROUP",       EN_STR},
    {"SOURCERPM",   EN_STR},
    {"LONGSIZE",    EN_LONG},
    {"LICENSE",     EN_STR},
    {"DSAHEADER",   EN_PGPSIG},
    {"RSAHEADER",   EN_PGPSIG},
    {"SIGGPG",      EN_PGPSIG},
    {"PACKAGER",    EN_STR},
    {"URL",         EN_STR},
    {"SUMMARY",     EN_STR},
    {"DESCRIPTION", EN_STR},
};

static const char * g_default_dbpath = "/var/lib/rpm";
static const char * g_dbapi = "3";

/**
 * @brief The CRpmQuery class 对RPM安装包信息查询的包装类
 * @link librpm.so
 * @link librpmio.so.1
 */
class CRpmQuery
{
public:
    /**
     * @brief rpm_configured 设置rpm的初始化配置信息
     * @param dbpath rpm数据库所在的库路径，设置需要查询的库路径
     */
    static void librpm_configured(const char *dbpath = g_default_dbpath);

    CRpmQuery();

    virtual ~CRpmQuery();

    /**
     * @brief query_all
     */
    void query_all();

    /**
     * @brief get_results 获取查询结果
     * @return
     */
    const TSoftwareList &get_results();

    /**
     * @brief clean_result 清理结果集
     */
    void clean_result();

private:
    int traverse_fields(Header h, SoftwarePackageInfos &software);

private:
    rpmts m_ts;
    TSoftwareList m_software_list;
};

}

#endif // LIBRPMCPP_H
